Assertions.php

<?php

namespace Taeluf;

trait Assertions {

    public function isInstanceOf($object, $shouldBe){
            $class = get_class($object);
        if ($object instanceof $shouldBe){
            $this->handleDidPass(true);
            echo "'$class' is instanceof '$shouldBe'";
        } else {
            $this->handleDidPass(false);
            echo "'$class' is NOT instanceof '$shouldBe'";
        }
    
    }

    public function str_contains($str, $target){
        if (is_array($target)){
            $success = true;
            foreach ($target as $strTarget){
                $oneSuccess = $this->str_contains($str,$strTarget);
                if (!$oneSuccess)$success = false;
            }
            return $success;
        }
        $pass = false;
        if (strpos($str,$target)!==false)$pass=true;

        $this->handleDidPass($pass);
        if ($pass){
            echo "String contains '$target'";
        } else {
            echo "String does not contain '$target'";
        }
        return false;
    }
    public function str_not_contains(string $str, $target){
        if (is_array($target)){
            $success = true;
            foreach ($target as $strTarget){
                $oneSuccess = $this->str_not_contains($str,$strTarget);
                if (!$oneSuccess)$success = false;
            }
            return $success;
        } else $target = (string)$target;
        $pass = true;
        if (strpos($str,$target)!==false)$pass=false;

        $this->handleDidPass($pass);
        if ($pass){
            echo "String does not contain '$target'";
        } else {
            echo "String contains '$target'";
        }
        return false;
    
    }

    public function catch($exceptionClass,$strict=false){
        $catcher = new Tester\ExceptionCatcher($exceptionClass);
        $this->catchers[] = $catcher;
        return $catcher;
    }
    public function throw($e){
        $list = $this->catchers;
        foreach ($list as $index => $cat){
            if ($cat->matches($e)){
                //@TODO allow one catcher to be re-used & just require that each exception be caught by at least one.
                unset($this->catchers[$index]);
                ob_start();
                $this->handleDidPass(true);
                ob_get_clean();
                // "Exception was caught";
                return true;
            }
        }
        $this->handleDidPass(false);
        echo "An exception was not handled...";
        throw $e;
    }

    public function compare($target, $actual,$strict=false){
        if (!$strict&&is_string($target)&&substr($target,0,7)=='file://'){
            $file = substr($target,7);
            if (!is_file($file)){
                throw new \Exception("{$target} is not a file. ");
            }
            $ext = substr($file,-4);
            if ($ext=='.php'){
                ob_start();
                require($file);
                $target=ob_get_clean();
            }
            else $target=file_get_contents($file);
        }
        if (!$strict&&is_string($actual)&&substr($actual,0,7)=='file://'){
            $file = substr($actual,7);
            if (!is_file($file)){
                throw new \Exception("{$actual} is not a file. ");
            }
            $ext = substr($file,-4);
            if ($ext=='.php'){
                ob_start();
                require($file);
                $actual=ob_get_clean();
            }
            else $actual=file_get_contents($file);
        }


        if (!$strict&&is_string($target)&&is_string($actual)){
            $target = trim($target);
            $actual = trim($actual);
        }
        $pass = false;
        if ($strict&&$target===$actual)$pass = true;
        else if ($target==$actual)$pass = true;


        $target = $this->comparisonOutput($target);
        $actual = $this->comparisonOutput($actual);
        
        // echo "Strict: ".($strict ? 'true' : 'false');

        $this->handleDidPass($pass);
        if ($strict)echo " strict comparison";
        $this->targetVsActualOutput($target, $actual);

        return $pass;
    }

    public function handleDidPass(bool $didPass){
        echo "\n\n";
        if ($didPass)echo "+++pass+++";
        else echo "---fail---";
        echo "\n";
        $passStr = $didPass ? 'true' : 'false';
        $this->comparisons[$passStr]++;
        return $didPass;
    }

    public function targetVsActualOutput($target, $actual){
        // echo "\n";
        echo "Target:\n{$target}";
        echo "\n--\n";
        echo "Actual:\n{$actual}";
        echo "\n--------\n";
    }
    public function comparisonOutput($value){
        if (is_object($value)){
            return "Object of class ".get_class($value);
        }
        if (is_array($value)){

            $pr = var_export($value, true);
            $maxLen= 1000;
            
            if (($this->options['prettyPrintArray'][0]??null)=='true'){
                $oneLine = $pr;
                $maxLen = 1500;
            } else {
                $oneLine = implode(" ",array_map('trim',explode("\n",$pr)));
            }
            $value = substr($oneLine,0,$maxLen);
            if (strlen($oneLine)>$maxLen)$value .= '...';

            return $value;
        }

        if ($value===true)return 'true';
        else if ($value===false)return 'false';

        return $value;
    }

}